package org.example.jwt1.handler;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;


//过滤器，获取Token
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {


    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //获取Token
        String token = request.getHeader("Authorization");//接收从前端发送过来的请求头
        //Token不为空则进行验证，验证是否过期，如果不过期则取出用户名和权限
        //再将用户名和权限交给UsernamePasswordAuthenticationToken重新认证
        //认证成功后则存入SecurityContext上下文，这时就跟正常登录一样了
        if (token != null) {
            // 解析token.
            Claims claims = Jwts.parser()
                    .setSigningKey("sike")  //密钥
                    .parseClaimsJws(token)
                    .getBody();
            //获取过期时间
            Date claimsExpiration = claims.getExpiration();
            //判断是否过期
            Date now = new Date();
            if (now.getTime() > claimsExpiration.getTime()) {
                throw new AuthenticationServiceException("凭证已过期，请重新登录！");
            }
            //从claims中获取authentication，它是一个LinkedHashMap类型
            LinkedHashMap authenticationMap = (LinkedHashMap<String, Object>) claims.get("authentication");
            //从authentication中获取用户名(也可以从claims的Subject属性中取用户名)
            String username = (String) authenticationMap.get("name");

            //获取保存在token中的登录认证成功的权限(authentication)，并将其转换成List<GrantedAuthority>
//            ArrayList<LinkedHashMap<String, String>> authenticationList = (ArrayList<LinkedHashMap<String, String>>) authenticationMap.get("authorities");
//            //将ArrayList<LinkedHashMap<String,String>>转换成字符串数组
//            String[] authenticationStr = new String[authenticationList.size()];
//            for (int i = 0; i < authenticationList.size(); i++) {
//                authenticationStr[i] = authenticationList.get(i).get("authority");
//            }
//            //将字符串数组权限转换成 List<GrantedAuthority>类型
//            List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList(authenticationStr);
            // 利用UsernamePasswordAuthenticationToken生成新的authentication
            List<GrantedAuthority> authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority("admin"));
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null,
                    authorities );
            // 放入到SecurityContextHolder，表示认证通过
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        filterChain.doFilter(request, response);
    }
}
